package main

import (
	"fmt"
	"wikisaver/models"

	"github.com/tidwall/gjson"
)

func parseline(line string) {
	eid := gjson.Get(line, "id")
	etype := gjson.Get(line, "type")
	fmt.Println(eid, etype)
	sendToSaver(models.Entity{Id: eid.String(), Type: etype.String()})

	// save labels descriptions aliases
	labels := gjson.Get(line, "labels")
	parseLabels(labels, eid.String())
	descriptions := gjson.Get(line, "descriptions")
	parseDescriptions(descriptions, eid.String())
	aliases := gjson.Get(line, "aliases")
	parseAliases(aliases, eid.String())

	// save sitelink
	if etype.String() == "item" {
		sitelinks := gjson.Get(line, "sitelinks")
		parseSitelinks(sitelinks, eid.String())
	}

	// save claims
	claims := gjson.Get(line, "claims")
	parseClaims(claims, eid.String())
}

func parseSitelinks(sitelinks gjson.Result, eid string) {
	sitelinks.ForEach(func(key, value gjson.Result) bool {
		site := value.Get("site")
		title := value.Get("title")
		badges := value.Get("badges")
		sendToSaver(models.SiteLink{Eid: eid, Site: site.String(), Title: title.String(), Badges: badges.String()})
		return true
	})
}

func parseLabels(labels gjson.Result, eid string) {
	labels.ForEach(func(key, value gjson.Result) bool {
		lang := value.Get("language")
		v := value.Get("value")
		sendToSaver(models.Label{Eid: eid, Language: lang.String(), Value: v.String()})
		return true
	})
}

func parseDescriptions(descriptinos gjson.Result, eid string) {
	descriptinos.ForEach(func(key, value gjson.Result) bool {
		lang := value.Get("language")
		v := value.Get("value")
		sendToSaver(models.Description{Eid: eid, Language: lang.String(), Value: v.String()})
		return true
	})
}

func parseAliases(aliases gjson.Result, eid string) {
	aliases.ForEach(func(key, arr gjson.Result) bool {
		arr.ForEach(func(key, value gjson.Result) bool {
			lang := value.Get("language")
			v := value.Get("value")
			sendToSaver(models.Alias{Eid: eid, Language: lang.String(), Value: v.String()})
			return true
		})
		return true
	})
}

func parseClaims(claims gjson.Result, eid string) {
	claims.ForEach(func(key, arr gjson.Result) bool {
		arr.ForEach(func(key, value gjson.Result) bool {
			ms := value.Get("mainsnak")
			id := value.Get("id").String()
			msid := parseSnak(ms, id)
			stype := value.Get("type").String()
			rank := value.Get("rank").String()
			sendToSaver(models.Statement{Id: id,Eid: eid, Msid: msid, Type: stype, Rank: rank})
			// save qualifiers
			qualifiers := value.Get("qualifiers")
			if qualifiers.Exists() {
				parseQualifiers(qualifiers, id)
			}

			// save references
			references := value.Get("references")
			if references.Exists() {
				parseReferences(references, id)
			}

			return true
		})
		return true
	})
}

func parseSnak(snak gjson.Result, sid string) int {
	sk := models.Snak{}
	models.SkidMu.Lock()
	sk.Id = sk.GetId()
	sk.Sid = sid
	models.SkidMu.Unlock()
	sk.Pid = snak.Get("property").String()
	sk.SnakType = snak.Get("snaktype").String()
	if sk.SnakType == "value" {
		sk.DataType = snak.Get("datatype").String()
		dataValue := snak.Get("datavalue.value")
		if sk.DataType == "wikibase-item" {
			sk.DataValue = "Q"+dataValue.Get("numeric-id").String()
		} else {
			sk.DataValue = dataValue.String()
		}
	}
	sendToSaver(sk)
	return sk.Id
}

func parseQualifiers(qualifiers gjson.Result, sid string) {
	qualifiers.ForEach(func(key, arr gjson.Result) bool {
		arr.ForEach(func(key, value gjson.Result) bool {
			qualifier := models.Qualifier{}
			qualifier.Sid = sid
			qualifier.Pid = value.Get("property").String()
			qualifier.Hash = value.Get("hash").String()
			qualifier.SnakType = value.Get("snaktype").String()
			if qualifier.SnakType == "value" {
				qualifier.DataType = value.Get("datatype").String()
				qualifier.DataValue = value.Get("datavalue.value").String()
			}
			sendToSaver(qualifier)
			return true
		})
		return true
	})
}

func parseReferences(references gjson.Result, sid string) {
	references.ForEach(func(key, r gjson.Result) bool {
		ref := models.Reference{}

		models.ReidMu.Lock()
		ref.Id = ref.GetId()
		models.ReidMu.Unlock()

		ref.Sid = sid
		ref.Hash = r.Get("hash").String()
		ref.SnakOrder = r.Get("snaks-order").String()
		sendToSaver(ref)
		
		// save snaks
		r.Get("snaks").ForEach(func(key, arr gjson.Result) bool {
			arr.ForEach(func(key, value gjson.Result) bool {
				skid := parseSnak(value, sid)
				sr := models.SR{Skid: skid, Rid: ref.Id}
				sendToSaver(sr)
				return true
			})
			return true
		})
		return true
	})
}

func sendToSaver(obj models.AddAble) {
	models.SaveChan <- obj
}
